package org.dromara.app.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import io.rong.models.group.GroupMember;
import io.rong.models.group.GroupModel;
import jakarta.servlet.http.HttpServletRequest;
import org.dromara.app.appParams.*;
import org.dromara.app.appReturn.AppActiveInfoReturn;
import org.dromara.app.appReturn.AppMemberReturn;
import org.dromara.app.appReturn.AppShopYueJuReturn;
import org.dromara.app.appReturn.AppYueJuListReturn;
import org.dromara.app.config.AppGoEasyUtil;
import org.dromara.app.config.AppRongYunUtil;
import org.dromara.app.cssUtils.CssUtils;
import org.dromara.app.cssUtils.RedisServiceUtils;
import org.dromara.app.domain.*;
import org.dromara.app.domain.vo.SkAppUserVo;
import org.dromara.app.domain.vo.SkShopVo;
import org.dromara.app.mapper.*;
import org.dromara.app.service.IBfExperienceLogService;
import org.dromara.common.core.constant.CacheNames;
import org.dromara.common.core.domain.model.LoginUser;
import org.dromara.common.core.utils.MapstructUtils;
import org.dromara.common.core.utils.StringUtils;
import org.dromara.common.mybatis.core.page.TableDataInfo;
import org.dromara.common.mybatis.core.page.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.RequiredArgsConstructor;
import org.dromara.common.redis.config.RedisConfig;
import org.dromara.common.redis.utils.RedisUtils;
import org.dromara.common.satoken.utils.LoginHelper;
import org.springframework.cache.annotation.CachePut;
import org.springframework.stereotype.Service;
import org.dromara.app.domain.bo.SkYueJuBo;
import org.dromara.app.domain.vo.SkYueJuVo;
import org.dromara.app.service.ISkYueJuService;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.Period;
import java.time.format.DateTimeFormatter;
import java.util.*;

/**
 * 约局信息Service业务层处理
 *
 * @author Evacuation
 * @date 2024-07-23
 */
@RequiredArgsConstructor
@Service
public class SkYueJuServiceImpl implements ISkYueJuService {

    private final SkYueJuMapper baseMapper;

    private final SkAppUserMapper skAppUserMapper;

    private final SkYueJuUserMapper skYueJuUserMapper;

    private final SkYueJuPinglunMapper skYueJuPinglunMapper;

    private final IBfExperienceLogService iBfExperienceLogService;

    private final AppRongYunUtil appRongYunUtil;

    private final SkShopMapper skShopMapper;



    /**
     * 查询约局信息
     *
     * @param id 主键
     * @return 约局信息
     */
    @Override
    public SkYueJuVo queryById(Long id) {
        return baseMapper.selectVoById(id);
    }

    /**
     * 分页查询约局信息列表
     *
     * @param bo        查询条件
     * @param pageQuery 分页参数
     * @return 约局信息分页列表
     */
    @Override
    public TableDataInfo<SkYueJuVo> queryPageList(SkYueJuBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<SkYueJu> lqw = buildQueryWrapper(bo);
        Page<SkYueJuVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    /**
     * 查询符合条件的约局信息列表
     *
     * @param bo 查询条件
     * @return 约局信息列表
     */
    @Override
    public List<SkYueJuVo> queryList(SkYueJuBo bo) {
        LambdaQueryWrapper<SkYueJu> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<SkYueJu> buildQueryWrapper(SkYueJuBo bo) {
        Map<String, Object> params = bo.getParams();
        //判断是否城市代理账户
        LoginUser user = LoginHelper.getLoginUser();
        if (user.getRolePermission().contains("cityAgent")) {
            //是城市代理人
            bo.setCity(user.getCity());
        }
        LambdaQueryWrapper<SkYueJu> lqw = Wrappers.lambdaQuery();
        lqw.eq(StringUtils.isNotBlank(bo.getType()), SkYueJu::getType, bo.getType());
        lqw.eq(StringUtils.isNotBlank(bo.getTitle()), SkYueJu::getTitle, bo.getTitle());
        lqw.eq(StringUtils.isNotBlank(bo.getContent()), SkYueJu::getContent, bo.getContent());
        lqw.eq(StringUtils.isNotBlank(bo.getImage()), SkYueJu::getImage, bo.getImage());
        lqw.eq(StringUtils.isNotBlank(bo.getAddress()), SkYueJu::getAddress, bo.getAddress());
        lqw.eq(StringUtils.isNotBlank(bo.getLongitude()), SkYueJu::getLongitude, bo.getLongitude());
        lqw.eq(StringUtils.isNotBlank(bo.getLatitude()), SkYueJu::getLatitude, bo.getLatitude());
        lqw.eq(bo.getAllUserNumber() != null, SkYueJu::getAllUserNumber, bo.getAllUserNumber());
        lqw.eq(bo.getManNumber() != null, SkYueJu::getManNumber, bo.getManNumber());
        lqw.eq(bo.getWoman() != null, SkYueJu::getWoman, bo.getWoman());
        lqw.eq(bo.getStartTime() != null, SkYueJu::getStartTime, bo.getStartTime());
        lqw.eq(StringUtils.isNotBlank(bo.getActivityTitle()), SkYueJu::getActivityTitle, bo.getActivityTitle());
        lqw.eq(StringUtils.isNotBlank(bo.getActivityAddress()), SkYueJu::getActivityAddress, bo.getActivityAddress());
        lqw.eq(StringUtils.isNotBlank(bo.getActivityStartTime()), SkYueJu::getActivityStartTime, bo.getActivityStartTime());
        lqw.eq(StringUtils.isNotBlank(bo.getActivityEndTime()), SkYueJu::getActivityEndTime, bo.getActivityEndTime());
        lqw.eq(StringUtils.isNotBlank(bo.getActivityTradeTime()), SkYueJu::getActivityTradeTime, bo.getActivityTradeTime());
        lqw.eq(StringUtils.isNotBlank(bo.getActivityUseStartTime()), SkYueJu::getActivityUseStartTime, bo.getActivityUseStartTime());
        lqw.eq(StringUtils.isNotBlank(bo.getActivityUseEndTime()), SkYueJu::getActivityUseEndTime, bo.getActivityUseEndTime());
        lqw.eq(bo.getActivityManPrice() != null, SkYueJu::getActivityManPrice, bo.getActivityManPrice());
        lqw.eq(bo.getActivityWomanPrice() != null, SkYueJu::getActivityWomanPrice, bo.getActivityWomanPrice());
        lqw.eq(StringUtils.isNotBlank(bo.getActivityRule()), SkYueJu::getActivityRule, bo.getActivityRule());
        lqw.eq(bo.getState() != null, SkYueJu::getState, bo.getState());
        lqw.eq(StringUtils.isNotBlank(bo.getCity()), SkYueJu::getCity, bo.getCity());
        lqw.eq(bo.getIsHall() != null, SkYueJu::getIsHall, bo.getIsHall());
        if (bo.getSourse() != null) {
            //未过期 未加入大厅  待审核约局
            if (bo.getSourse().longValue() == 1) {
                lqw.gt(SkYueJu::getEndTime, new Date());
                lqw.eq(SkYueJu::getState, 2);
            }
            //未过期 已加入大厅
            if (bo.getSourse().longValue() == 2) {
                lqw.gt(SkYueJu::getEndTime, new Date());
                lqw.eq(SkYueJu::getIsHall, 1);
                lqw.eq(SkYueJu::getState, 1);
            }
            //已过期或者取消
            if (bo.getSourse().longValue() == 3) {
                lqw.eq(SkYueJu::getState, 0).or(lqw1 -> lqw1.lt(SkYueJu::getEndTime, new Date()));
            }
        }
        lqw.orderByDesc(SkYueJu::getCreateTime);
        return lqw;
    }

    /**
     * 新增约局信息
     *
     * @param bo 约局信息
     * @return 是否新增成功
     */
    @Override
    public Boolean insertByBo(SkYueJuBo bo) {
        SkYueJu add = MapstructUtils.convert(bo, SkYueJu.class);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setId(add.getId());
        }
        return flag;
    }

    /**
     * 修改约局信息
     *
     * @param bo 约局信息
     * @return 是否修改成功
     */
    @Override
    public Boolean updateByBo(SkYueJuBo bo) {
        SkYueJu update = MapstructUtils.convert(bo, SkYueJu.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(SkYueJu entity) {
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 校验并批量删除约局信息信息
     *
     * @param ids     待删除的主键集合
     * @param isValid 是否进行有效性校验
     * @return 是否删除成功
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if (isValid) {
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteByIds(ids) > 0;
    }

    /**
     * 推荐列表
     *
     * @param params
     * @param req
     * @return
     */
    @Override
    public List<AppYueJuListReturn> recommendList(AppTuiJianParams params, HttpServletRequest req) {
        List<AppYueJuListReturn> list = baseMapper.recommendList(params);
        //年龄计算
        if (list.size() > 0) {
            for (AppYueJuListReturn app : list) {
                //初始化默认年龄
                app.setAge("0");
                if (app.getBirthday() != null && !app.getBirthday().equals("")) {
                    if (CssUtils.isValidYearMonth(app.getBirthday())) {
                        //实际年龄按照生日计算
                        LocalDate bir = LocalDate.parse(app.getBirthday() + "-01", DateTimeFormatter.ofPattern("yyyy-MM-dd"));
                        Period age = Period.between(bir, LocalDate.now());
                        if (age.getYears() > 0) {
                            app.setAge(age.getYears() + "");
                        }
                    }
                }
                if (app.getVipTime() != null) {
                    //判断是否是会员
                    if (app.getVipType().longValue() > 0) {
                        if (app.getVipTime().getTime() < new Date().getTime()) {
                            app.setVipType(0L);
                        }
                    }
                } else {
                    app.setVipType(0L);
                }

                if (app.getJuli() != null) {
                    app.setJuli(app.getJuli().setScale(2, BigDecimal.ROUND_CEILING));
                }

            }
        }
        return list;
    }

    /**
     * 派对大厅
     *
     * @param params
     * @param req
     * @return
     */
    @Override
    public List<AppYueJuListReturn> partyHall(AppTuiJianParams params, HttpServletRequest req) {
        List<AppYueJuListReturn> list = baseMapper.partyHall(params);
        return list;
    }

    /**
     * 灵魂达人匹配
     */
    @Override
    public AppYueJuListReturn getSoulMasterMatching(AppTongYongParams app, HttpServletRequest req) {
        AppYueJuListReturn appYueJuListReturn = new AppYueJuListReturn();
        Long userId = CssUtils.getUserId(req);
        SkAppUserVo user = skAppUserMapper.selectVoById(userId);
        //组装数据
        if (user.getPersonalityTag() != null) {
            List<String> tag = JSONUtil.toList(user.getPersonalityTag(), String.class);
            user.setTag(tag);
        }
        List<AppYueJuListReturn> list = baseMapper.getSoulMasterMatching(app, user);
        if (list.size() > 0) {
            Random random = new Random();
            int index = random.nextInt(list.size());
            appYueJuListReturn = list.get(index);
            appYueJuListReturn.setJuli(appYueJuListReturn.getJuli().setScale(2, BigDecimal.ROUND_CEILING));
        }
        return appYueJuListReturn;
    }

    /**
     * 发布约局
     *
     * @param app
     * @param req
     */
    @Override
    public SkYueJu publishContract(AppFaBuYueJuParams app, HttpServletRequest req) {
        Long userId = CssUtils.getUserId(req);
        Long allNumber = 0L;
        if (app.getManNumber() != null) {
            allNumber = app.getManNumber();
        }
        if (app.getWoman() != null) {
            allNumber = allNumber + app.getWoman();
        }
        if (allNumber.longValue() != app.getAllUserNumber().longValue()) {
            throw new RuntimeException("男女人数和总人数不匹配");
        }
        SkYueJu model = BeanUtil.copyProperties(app, SkYueJu.class);
        if(StringUtils.isEmpty(app.getUnlimited()) || (StringUtils.isNotEmpty(app.getUnlimited()) && app.getUnlimited().equals("0"))){
            model.setStartTime(new Date());
            Date endTime = DateUtil.offsetHour(model.getStartTime(), model.getLongTime());
            model.setEndTime(endTime);
        }

        if (app.getState().equals("1")){
            model.setState(1L);
        }else{
            model.setState(2L);
        }
        model.setIsHall(1L);
        model.setUserId(userId);
        baseMapper.insert(model);
        if(model.getState().longValue()==1){
            try {
                this.updateisHall(model.getId()+"");
            }catch (Exception e){

            }
        }
        return model;
    }

    /**
     * 约局详情
     *
     * @param params
     * @param req
     * @return
     */
    @Override
    public AppYueJuListReturn getYueJuInfo(AppDetailByIdParams params, HttpServletRequest req) {
        Long userId = CssUtils.getUserId(req);
        SkYueJu skYueJu = baseMapper.selectById(params.getId());
        AppYueJuListReturn app = BeanUtil.copyProperties(skYueJu, AppYueJuListReturn.class);
        if(app == null){
            return null;
        }
        //约局人列表
        List<AppYueJuUserInfoParam> list = skYueJuUserMapper.getYueJuInfo(params.getId());
        app.setList(list);
        //还差多少人
        Long chaPeople = app.getAllUserNumber().longValue() - list.size();
        app.setChaPeople(chaPeople);
        //发布人信息
        SkAppUser skAppUser = skAppUserMapper.selectById(skYueJu.getUserId());
        AppYueJuUserInfoParam appYueJuUserInfoParam = BeanUtil.copyProperties(skAppUser, AppYueJuUserInfoParam.class);
        app.setAppUser(appYueJuUserInfoParam);
        //评论条数
        Long cpmmontNumber = skYueJuPinglunMapper.selectCount(
            new QueryWrapper<SkYueJuPinglun>().lambda()
                .eq(SkYueJuPinglun::getYuejuId, params.getId())
        );
        app.setCommontNumber(cpmmontNumber == null ? 0L : cpmmontNumber);
        //点赞条数
        Object likeNumber = RedisUtils.getCacheObject(RedisServiceUtils.getYueJuAllZanNumber(params.getId()));
        app.setLikeNumber(likeNumber == null ? 0 : Integer.parseInt(likeNumber + ""));
        //是否点赞
        Object isLike = RedisUtils.getCacheMapValue(RedisServiceUtils.getYueJuLikeuser(params.getId()), userId.toString());
        if (isLike != null) {
            app.setIsLike(1);
        } else {
            app.setIsLike(0);
        }
        if (userId.longValue() == skYueJu.getUserId().longValue()) {
            app.setYuejuState(5L);
        } else {
            //判断是否已加入
            SkYueJuUser number = skYueJuUserMapper.selectOne(
                new QueryWrapper<SkYueJuUser>().lambda()
                    .eq(SkYueJuUser::getUserId, userId)
                    .eq(SkYueJuUser::getYueJuId, params.getId())
                    .last("limit 1")
            );
            /**
             * 0：未加入
             * 1：待审核
             * 2：已通过
             * 3：已拒绝
             * 4：已取消
             * 5：自己的
             */
            if (number != null) {
//                0:待审核  1：已通过 2：已拒绝
                if (number.getState().longValue() == 0) {
                    app.setYuejuState(1L);
                } else if (number.getState().longValue() == 1) {
                    app.setYuejuState(2L);
                } else if (number.getState().longValue() == 2) {
                    app.setYuejuState(3L);
                } else {
                    app.setYuejuState(0L);
                }
                //判断是否取消
                if (number.getIsCencel().longValue() == 1) {
                    app.setYuejuState(4L);
                }
            } else {
                app.setYuejuState(0L);
            }
        }

        return app;
    }

    /**
     * 约局点赞
     *
     * @param params
     * @param req
     */
    @Override
    public void yueJuLikes(AppDetailByIdParams params, HttpServletRequest req) {
        Long userId = CssUtils.getUserId(req);
        Object isno = RedisUtils.getCacheMapValue(RedisServiceUtils.getYueJuLikeuser(params.getId()), userId.toString());
        if (isno == null) {//增加
            RedisUtils.setCacheMapValue(RedisServiceUtils.getYueJuLikeuser(params.getId()), userId.toString(), 0);
            Object allnumber = RedisUtils.getCacheObject(RedisServiceUtils.getYueJuAllZanNumber(params.getId()));
            if (allnumber == null) {
                RedisUtils.setCacheObject(RedisServiceUtils.getYueJuAllZanNumber(params.getId()), 1);
            } else {
                RedisUtils.setCacheObject(RedisServiceUtils.getYueJuAllZanNumber(params.getId()), Integer.valueOf(allnumber.toString()) + 1);
            }
        } else {//减少
            RedisUtils.delCacheMapValue(RedisServiceUtils.getYueJuLikeuser(params.getId()), userId.toString());
            Object allnumber = RedisUtils.getCacheObject(RedisServiceUtils.getYueJuAllZanNumber(params.getId()));
            if (allnumber != null) {
                RedisUtils.setCacheObject(RedisServiceUtils.getYueJuAllZanNumber(params.getId()), Integer.valueOf(allnumber.toString()) - 1);
            }
        }

    }

    /**
     * 约局活动列表
     *
     * @param params
     * @param req
     * @return
     */
    @Override
    public List<AppActiveInfoReturn> activeList(AppPageParams params, HttpServletRequest req) {
        Long userId = CssUtils.getUserId(req);
        List<AppActiveInfoReturn> list = baseMapper.activeList(params, params.getUserId());
        return list;
    }

    /**
     * 申请加入群组列表（审核中）
     *
     * @param req
     * @return
     */
    @Override
    public List<AppYueJuListReturn> getYueJuShengHeList(HttpServletRequest req) {
        List<AppYueJuListReturn> list = baseMapper.getYueJuShengHeList(CssUtils.getUserId(req));
        return list;
    }

    @Override
    public int updateisHall(String id) throws Exception {
        SkYueJu skYueJu = baseMapper.selectById(id);
        skYueJu.setState(1L);
        // 创建群聊
        GroupMember[] members = new GroupMember[]{new GroupMember().setId(skYueJu.getUserId() + "")};
        GroupModel groupModel = new GroupModel()
            .setId(skYueJu.getId() + "")
            .setName(skYueJu.getTitle() + "&|*&" + skYueJu.getImage().split(",")[0])
            .setMembers(members);
        appRongYunUtil.create(groupModel);

        skYueJu.setIsGroup(1L);

        SkAppUser user = skAppUserMapper.selectById(skYueJu.getUserId());
        List<AppMemberReturn> list = new ArrayList<>();
        if (user.getHeadImage() != null && !user.getHeadImage().equals("")) {
            AppMemberReturn app = new AppMemberReturn();
            app.setUserId(user.getId());
            app.setHeadImage(user.getHeadImage());
            list.add(app);
        }
        if(list.size()>0){
            skYueJu.setGroupHeadImage(JSONUtil.toJsonStr(list));
        }
        //添加经验值
        //自己发布组局  添加经验值
        String obej = iBfExperienceLogService.getKeyValue("自己发布组局");
        System.out.println(obej);
        if (obej == null) {
            obej = "0";
        }
        iBfExperienceLogService.addLog(skYueJu.getUserId(), obej, "自己发布组局");
        //我的直推发布组局  添加经验值
        if (user.getYqUserId() != null) {
            String obej2 = iBfExperienceLogService.getKeyValue("我的直推发布组局");
            if (obej2 == null) {
                obej2 = "0";
            }
            iBfExperienceLogService.addLog(user.getYqUserId(), obej2, "我的直推发布组局");
        }
        return baseMapper.updateById(skYueJu);
    }

    @Override
    public int updateisHalljujue(String id) {
        SkYueJu skYueJu = baseMapper.selectById(id);
        skYueJu.setState(3L);
        return baseMapper.updateById(skYueJu);
    }

    /**
     * 待审核约局列表
     *
     * @return
     */
    @Override
    public List<SkYueJuVo> getShList() {
        List<SkYueJuVo> list = baseMapper.selectVoList(
            new QueryWrapper<SkYueJu>().lambda()
                .eq(SkYueJu::getState, 2)
                .ge(SkYueJu::getEndTime, new Date())
        );
        return list;
    }

    /**
     * 商家标签约局列表
     */
    @Override
    public List<AppShopYueJuReturn> getShopYueJuList(AppDetailByIdParams params, HttpServletRequest req) {
        SkShopVo shop = skShopMapper.selectVoById(params.getId());
        List<AppShopYueJuReturn> list = baseMapper.getShopYueJuList(JSONUtil.toList(shop.getType(),String.class),params);
        return list;
    }

    /**
     * 编辑群公告、简介
     */
    @Override
    public void updateGroupNoticeSynopsis(AppYueJuGroupNodeParams app, Long userId) {
        SkYueJu skYueJu = baseMapper.selectById(app.getYuejuId());
        skYueJu.setNotice(app.getNotice());
        skYueJu.setSynopsis(app.getSynopsis());
        baseMapper.updateById(skYueJu);
    }

    @Override
    public AppYueJuListReturn getYueJuInfoNotLogin(AppDetailByIdParams params) {
        SkYueJu skYueJu = baseMapper.selectById(params.getId());
        AppYueJuListReturn app = BeanUtil.copyProperties(skYueJu, AppYueJuListReturn.class);
        //约局人列表
        List<AppYueJuUserInfoParam> list = skYueJuUserMapper.getYueJuInfo(params.getId());
        app.setList(list);
        //还差多少人
        Long chaPeople = app.getAllUserNumber().longValue() - list.size();
        app.setChaPeople(chaPeople);
        //发布人信息
        SkAppUser skAppUser = skAppUserMapper.selectById(skYueJu.getUserId());
        AppYueJuUserInfoParam appYueJuUserInfoParam = BeanUtil.copyProperties(skAppUser, AppYueJuUserInfoParam.class);
        app.setAppUser(appYueJuUserInfoParam);
        //评论条数
        Long cpmmontNumber = skYueJuPinglunMapper.selectCount(
            new QueryWrapper<SkYueJuPinglun>().lambda()
                .eq(SkYueJuPinglun::getYuejuId, params.getId())
        );
        app.setCommontNumber(cpmmontNumber == null ? 0L : cpmmontNumber);
        //点赞条数
        Object likeNumber = RedisUtils.getCacheObject(RedisServiceUtils.getYueJuAllZanNumber(params.getId()));
        app.setLikeNumber(likeNumber == null ? 0 : Integer.parseInt(likeNumber + ""));
        return app;
    }


}
